﻿using System;
using System.Collections.Generic;

namespace nRoute.Components.Composition
{
    public class ResourceKeyComparer
        : EqualityComparer<ResourceKey>
    {
        private const int FACTOR = 214626;
        private static ResourceKeyComparer _default = new ResourceKeyComparer();

        private ResourceKeyComparer() { }

        public static ResourceKeyComparer Default
        {
            get { return _default; }
        }

#region IEqualityComparer related

        public override bool Equals(ResourceKey x, ResourceKey y)
        {
            // the idea being null keys can't be compared
            if (x.Type == y.Type)
            {
                if (x.Key == null || y.Key == null)
                {
                    return false;
                }
                return string.Equals(x.Key, y.Key, Utilities.Compatability.INVARIANT_IGNORECASE_STRING_COMPARISION);
            }
            return false;
        }

        public override int GetHashCode(ResourceKey obj)
        {
            // if the key is not unique then we try
            if (obj.Key != null)
            {
                return RSHash(obj.Key, obj.Type);
            }
            else
            {
                return obj.GetHashCode();
            }
        }

        // idea from http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode
        private static int RSHash(params object[] input)
        {
            var _a = 63689;
            var _hash = 158;

            unchecked
            {
                for (int i = 0; i < input.Length; i++)
                {
                    if (input[i] != null)
                    {
                        _hash = _hash * _a + input[i].GetHashCode();
                        _a = _a * FACTOR;
                    }
                }
            }

            return _hash;
        }

#endregion

    }
}
